#include "devicemanagementui.h"
#include "ui_devicemanagementui.h"

#include <QMessageBox>
#include <QDebug>

SlaveComputerManagement::SlaveComputerManagement(QDialog *parent) :
    QDialog(parent),
    ui(new Ui::SlaveComputerManagement)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::CustomizeWindowHint|Qt::WindowCloseButtonHint);

    ui->filterItem_status->hide();
    ui->deviceTable->hideColumn(8);
    /* 自适应宽度 */
    ui->deviceTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

    /* 初始化 */
    cusMsg = new CustomMessageBox();
    DMDB = new DeviceManagement();
    addNDev = new AddNewDevice();
    reviseDeviceInfo = new ReviseDeviceInfo();

    connect(ui->newDevice, &QPushButton::clicked, this, [=](){
        addNDev->exec();
    });
    connect(addNDev, SIGNAL(newDeviceInfo(AddNewDevice::DeviceStruct)), this, SLOT(addNewDeviceInfoToDB(AddNewDevice::DeviceStruct)));
    connect(ui->filterKey, SIGNAL(currentIndexChanged(int)), this, SLOT(changeFilterCondition(int)));
    connect(ui->filter, &QPushButton::clicked, this, &SlaveComputerManagement::filterDeviceTable);
    connect(reviseDeviceInfo, &ReviseDeviceInfo::sendNewDeviceInfo, this, [=](int row, QString name, QString ip, QString port){
        /* 修改table中设备信息 */
        ui->deviceTable->item(row, 0)->setText(name);
        ui->deviceTable->item(row, 3)->setText(ip);
        ui->deviceTable->item(row, 4)->setText(port);
        /* 更新 */
        this->reviseDeviceTable(row);
    });
    connect(ui->reset, &QPushButton::clicked, this, [=](){
        ui->filterItem->clear();
        for(int i = 0; i < ui->deviceTable->rowCount(); i++)
            ui->deviceTable->showRow(i);
    });
    connect(ui->ok, &QPushButton::clicked, this, [=]{
        this->close();
    });

    // 调用show方法
    QList<QHash<QString,QString>> allDeviceInfos = DMDB->show();
    /* 渲染 */
    this->renderDeviceInfo(allDeviceInfos);
}

SlaveComputerManagement::~SlaveComputerManagement()
{
    delete ui;
}

/* 渲染设备信息到表格中 */
void SlaveComputerManagement::renderDeviceInfo(QList<QHash<QString, QString>> allDeviceInfos){
    int disconnected = 0, connected = 0, running = 0, stoppage = 0, paused = 0, debounce = 0;

    ui->deviceTable->blockSignals(true);    // 阻塞信号

    ui->deviceTable->setRowCount(0);
    for(int i = 0; i < connectDeviceInfo.size(); i++){
        QHash<QString, QString> deviceInfo = allDeviceInfos[i];

        QWidget* btnsW = new QWidget();
        QHBoxLayout* hBoxLayout = new QHBoxLayout(btnsW);
        QPushButton *deleteDev = new QPushButton();
        deleteDev->setText("删除");
        deleteDev->setStyleSheet("background: transparent; border: none; font-family: 'Alibaba PuHuiTi';");
        deleteDev->setCursor(Qt::PointingHandCursor);

        QPushButton *refreshDev = new QPushButton();
        refreshDev->setText("刷新");
        refreshDev->setStyleSheet("background: transparent; border: none; font-family: 'Alibaba PuHuiTi';");
        refreshDev->setCursor(Qt::PointingHandCursor);

        QPushButton *updateDev = new QPushButton();
        updateDev->setText("更新");
        updateDev->setStyleSheet("background: transparent; border: none; font-family: 'Alibaba PuHuiTi';");
        updateDev->setCursor(Qt::PointingHandCursor);

        hBoxLayout->addWidget(deleteDev);
        hBoxLayout->addWidget(refreshDev);
        hBoxLayout->addWidget(updateDev);
        hBoxLayout->setMargin(5);

        /* 设置表格不可编辑 */
        ui->deviceTable->setEditTriggers(QAbstractItemView::NoEditTriggers);

        QString ip = deviceInfo["ip"];
        int port = deviceInfo["port"].toInt();
        int row = ui->deviceTable->rowCount();

        /* 将设备信息添加到表格中 */
        ui->deviceTable->setRowCount(row+1);
        ui->deviceTable->setItem(row, 0, new QTableWidgetItem(deviceInfo["name"]));
        ui->deviceTable->setItem(row, 1, new QTableWidgetItem(deviceInfo["serial_number"]));
        ui->deviceTable->setItem(row, 3, new QTableWidgetItem(deviceInfo["ip"]));
        ui->deviceTable->setItem(row, 4, new QTableWidgetItem(deviceInfo["port"]));
        ui->deviceTable->setItem(row, 5, new QTableWidgetItem(deviceInfo["mac"]));
        ui->deviceTable->setCellWidget(row, 7, btnsW);
        ui->deviceTable->setItem(row, 8, new QTableWidgetItem(deviceInfo["id"]));

        /* 设备连接 */
        QTableWidgetItem *tItem = new QTableWidgetItem(connectDeviceInfo[i].dev.status);
        ui->deviceTable->setItem(row, 2, tItem);
        /* 修改设备状态颜色 */
        /* 已连接 */
        if(connectDeviceInfo[i].dev.status == "已连接"){
            ui->deviceTable->item(row, 2)->setForeground(QColor(16, 0, 235));
        }
        /* 运行中 */
        else if(connectDeviceInfo[i].dev.status == "运行中"){
            ui->deviceTable->item(row, 2)->setForeground(QColor(8, 103, 0));
        }
        /* 故障 */
        else if(connectDeviceInfo[i].dev.status == "故障"){
            ui->deviceTable->item(row, 2)->setForeground(QColor(182, 0, 0));
        }

        /* 故障信息 */
        if(connectDeviceInfo[i].msg.size() != 0){
            QTableWidgetItem *tMsg = new QTableWidgetItem(connectDeviceInfo[i].msg[2]);
            ui->deviceTable->setItem(row, 6, tMsg);
        }
        else {
            QTableWidgetItem *tMsg = new QTableWidgetItem("");
            ui->deviceTable->setItem(row, 6, tMsg);
        }

        /* 删除设备按钮 */
        connect(deleteDev, &QPushButton::clicked, this, [=](){
            QString queryText = "确认删除设备 \"" + deviceInfo["name"] + "\" ?";
            if(QMessageBox::Yes == cusMsg->show(this, CMsg::CQuestion, "确认删除", queryText)){
                DMDB->remove(deviceInfo["id"]);
                /* 从数组中去除 */
                connectDeviceInfo.removeAt(i);
                // 调用show方法
                QList<QHash<QString,QString>> allDeviceInfos = DMDB->show();
                this->renderDeviceInfo(allDeviceInfos);
            }
        });

        /* 刷新设备按钮 */
        connect(refreshDev, &QPushButton::clicked, this, [=]() mutable {
            /* 防抖 */
            if(debounce == 0){
                debounce = 1;
                /* 重新建立连接 */
                qDebug() << ip << port;
                //                /* 关闭链接 */
                //                connectDeviceInfo[i].instructionsService->m_socketClient->closeSocket();
                /* 如果未连接 */
                if(!connectDeviceInfo[i].instructionsService->m_socketClient->isConnected()){
                    /* 重新建立链接 */
                    if(connectDeviceInfo[i].instructionsService->establishConnection(ip, port)){
                        this->sleep(EXPERIMENT_RUNNING_SLEEP_TIME);

                        /* 发送请求自检命令 */
                        connectDeviceInfo[i].instructionsService->sendChecking(connectDeviceInfo[i].dev.id);
                        this->sleep(EXPERIMENT_RUNNING_SLEEP_TIME);

                        // 连接成功
                        qDebug() << "连接成功";
                        connectDeviceInfo[i].msg = connectDeviceInfo[i].instructionsService->ziJianData;

                        if(connectDeviceInfo[i].msg.size() != 0){
                            if(connectDeviceInfo[i].msg[2].contains("成功"))
                                connectDeviceInfo[i].dev.status = "已连接";

                            else if(connectDeviceInfo[i].msg[2].contains("运行") && !connectDeviceInfo[i].msg[2].contains("不运行"))
                                connectDeviceInfo[i].dev.status = "运行中";
                            else{
                                connectDeviceInfo[i].dev.status = "故障";
                            }
                        }
                        else {
                            connectDeviceInfo[i].dev.status = "已连接";
                        }
                    }
                    else {
                        connectDeviceInfo[i].msg = connectDeviceInfo[i].instructionsService->ziJianData;
                        connectDeviceInfo[i].dev.status = "未连接";
                    }
                    /* socket关闭 */
                    if(connectDeviceInfo[i].instructionsService->m_socketClient->isConnected()){
                        connectDeviceInfo[i].instructionsService->m_socketClient->closeSocket();
                    }
                }
                // 调用show方法
                QList<QHash<QString,QString>> allDeviceInfos = DMDB->show();
                this->renderDeviceInfo(allDeviceInfos);
                this->sleep(50);
                debounce = 0;
            }
        });
        connect(updateDev, &QPushButton::clicked, this , [=](){
            /* 显示窗口 */
            reviseDeviceInfo->show();
            /* 发送当前设备数据 */
            reviseDeviceInfo->renderCurrentInfo(row, connectDeviceInfo[i].dev.name, connectDeviceInfo[i].dev.ip, connectDeviceInfo[i].dev.port, connectDeviceInfo[i].dev.id);
        });
    }

    ui->deviceTable->blockSignals(false);    // 恢复信号
}

/* 改变过滤条件 */
void SlaveComputerManagement::changeFilterCondition(int index){
    this->index = index;
    if(index == 2){
        ui->filterItem->hide();
        ui->filterItem_status->show();
    }
    else {
        ui->filterItem->show();
        ui->filterItem_status->hide();
    }
}

void SlaveComputerManagement::filterDeviceTable(){
    for(int i = 0; i < ui->deviceTable->rowCount(); i++) ui->deviceTable->showRow(i);
    if(ui->filterCondition->currentIndex() == 0){
        switch(this->index){
        case 0:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem->displayText() != ui->deviceTable->item(i, 0)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;

        case 1:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem->displayText() != ui->deviceTable->item(i, 1)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;
        case 2:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem_status->currentText() != ui->deviceTable->item(i, 2)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;
        case 3:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem->displayText() != ui->deviceTable->item(i, 3)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;
        case 4:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem->displayText() != ui->deviceTable->item(i, 4)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;
        case 5:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem->displayText() != ui->deviceTable->item(i, 5)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;
        }
    }
    else {
        switch(this->index){
        case 0:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem->displayText() == ui->deviceTable->item(i, 0)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;

        case 1:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem->displayText() == ui->deviceTable->item(i, 1)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;
        case 2:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem_status->currentText() == ui->deviceTable->item(i, 2)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;
        case 3:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem->displayText() == ui->deviceTable->item(i, 3)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;
        case 4:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem->displayText() == ui->deviceTable->item(i, 4)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;
        case 5:
            for(int i = 0; i < ui->deviceTable->rowCount(); i++){
                if(ui->filterItem->displayText() == ui->deviceTable->item(i, 5)->text()){
                    ui->deviceTable->hideRow(i);
                }
            }
            break;
        }
    }
}

void SlaveComputerManagement::addNewDeviceInfoToDB(AddNewDevice::DeviceStruct newDevice){
    DMDB->create(
                newDevice.deviceName,
                newDevice.MACAddr,
                newDevice.IPAddr,
                newDevice.Port,
                newDevice.serialNumber,
                "未连接");
    /* 加入到设备数组中 */
    ConnectedDeviceStruct cDev;
    cDev.dev.name = newDevice.deviceName;
    cDev.dev.mac = newDevice.MACAddr;
    cDev.dev.ip = newDevice.IPAddr;
    cDev.dev.port = newDevice.Port;
    cDev.dev.serial_number = newDevice.serialNumber;
    cDev.dev.status = "未连接";
    cDev.instructionsService = new InstructionsService();
    QList<QHash<QString, QString>> allDeviceInfos = DMDB->show();
    /* 添加设备ID */
    cDev.dev.id = allDeviceInfos[allDeviceInfos.size()-1]["id"];
    connectDeviceInfo.append(cDev);
    this->renderDeviceInfo(allDeviceInfos);
}

void SlaveComputerManagement::reviseDeviceTable(int row){
    // 更新 设备列表
    for(int i = 0; i < connectDeviceInfo.size(); i++){
        if(connectDeviceInfo[i].dev.id == ui->deviceTable->item(row, 8)->text()){
            /* 暂存原ip，端口，设备名称 */
            QString preDevName, preDevIp, preDevPort;
            preDevName = connectDeviceInfo[i].dev.name;
            preDevIp = connectDeviceInfo[i].dev.ip;
            preDevPort = connectDeviceInfo[i].dev.port;

            qDebug() << "原设备信息" << preDevName << preDevIp << preDevPort;

            /* 存入新ip，端口，设备名称 */
            connectDeviceInfo[i].dev.name = ui->deviceTable->item(row, 0)->text();
            connectDeviceInfo[i].dev.ip = ui->deviceTable->item(row, 3)->text();
            connectDeviceInfo[i].dev.port = ui->deviceTable->item(row, 4)->text();

            if(connectDeviceInfo.size() != 0){
                QStringList ipStringList = connectDeviceInfo[i].dev.ip.split(".");
                /* ip地址格式有误 */
                if(ipStringList.size() != 4){
                    /* 改回原信息 */
                    connectDeviceInfo[i].dev.name = preDevName;
                    connectDeviceInfo[i].dev.ip = preDevIp;
                    connectDeviceInfo[i].dev.port = preDevPort;

                    cusMsg->show(this, CMsg::CCritical, "错误", "IP地址格式错误");
                }
                /* ip地址格式正确 */
                else {
                    qDebug() << "改变IP";

                    qDebug() << connectDeviceInfo[i].dev.ip << "connectDeviceInfo[i].dev.ip";
                    qDebug() << connectDeviceInfo[i].dev.port << "connectDeviceInfo[i].dev.port";
                    qDebug() << connectDeviceInfo[i].dev.name << "connectDeviceInfo[i].dev.name";

                    /* 建立连接 */
                    if(!connectDeviceInfo[i].instructionsService->m_socketClient->isConnected()){
//                        connectDeviceInfo[i].instructionsService->establishConnection(connectDeviceInfo[i].dev.ip, connectDeviceInfo[i].dev.port.toInt());
                        connectDeviceInfo[i].instructionsService->establishConnection(preDevIp, preDevPort.toInt());
                    }
                    /* 发送请求自检命令，判断设备状态 */
                    connectDeviceInfo[i].instructionsService->sendChecking(connectDeviceInfo[i].dev.id);
                    this->sleep(EXPERIMENT_RUNNING_SLEEP_TIME);

                    /* 获取自检信息，判断是否为其他状态 */
                    connectDeviceInfo[i].msg = connectDeviceInfo[i].instructionsService->ziJianData;
                    if(connectDeviceInfo[i].msg.size() != 0){
                        if(connectDeviceInfo[i].msg[2].contains("成功"))
                            connectDeviceInfo[i].dev.status = "已连接";
                        else if(connectDeviceInfo[i].msg[2].contains("运行") && !connectDeviceInfo[i].msg[2].contains("不运行")){
                            connectDeviceInfo[i].dev.status = "运行中";
                            cusMsg->show(this, CMsg::CInformation, "设备库", "实验运行中，设备信息修改失败！");
                            /* 改回原信息 */
                            connectDeviceInfo[i].dev.name = preDevName;
                            connectDeviceInfo[i].dev.ip = preDevIp;
                            connectDeviceInfo[i].dev.port = preDevPort;
                            ipData = "";
                            // 调用show方法
                            QList<QHash<QString,QString>> allDeviceInfos = DMDB->show();
                            /* 渲染 */
                            this->renderDeviceInfo(allDeviceInfos);
                            return;
                        }
                        else{
                            connectDeviceInfo[i].dev.status = "故障";
                            cusMsg->show(this, CMsg::CCritical, "设备库", "设备故障，IP修改失败！");
                            /* 改回原信息 */
                            connectDeviceInfo[i].dev.name = preDevName;
                            connectDeviceInfo[i].dev.ip = preDevIp;
                            connectDeviceInfo[i].dev.port = preDevPort;
                            ipData = "";
                            // 调用show方法
                            QList<QHash<QString,QString>> allDeviceInfos = DMDB->show();
                            /* 渲染 */
                            this->renderDeviceInfo(allDeviceInfos);
                            return;
                        }
                    }
                    else {
                        connectDeviceInfo[i].dev.status = "已连接";
                    }

                    /* 修改ip */
                    /* 初始化 */
                    connectDeviceInfo[i].instructionsService->ziJianData.clear();
                    connectDeviceInfo[i].instructionsService->ipData = "";

                    connectDeviceInfo[i].instructionsService->sendIP(ipStringList[0], ipStringList[1], ipStringList[2], ipStringList[3], connectDeviceInfo[i].dev.port);
                    this->sleep(EXPERIMENT_RUNNING_SLEEP_TIME);
                    ipData = connectDeviceInfo[i].instructionsService->getIpData();

                    qDebug() << "ipData" << ipData;

                    /* IPData不为空 */
                    if(ipData != 0){
                        cusMsg->show(this, CMsg::CInformation, "设备库", "设备信息修改成功！");

                        /* 更新设备信息 */
                        connectDeviceInfo[i].dev.name = ui->deviceTable->item(row, 0)->text();
                        connectDeviceInfo[i].dev.mac = ui->deviceTable->item(row, 5)->text();
                        connectDeviceInfo[i].dev.ip = ui->deviceTable->item(row, 3)->text();
                        connectDeviceInfo[i].dev.port = ui->deviceTable->item(row, 4)->text();
                        connectDeviceInfo[i].dev.serial_number = ui->deviceTable->item(row, 1)->text();

                        /* 更新数据库设备信息 */
                        DMDB->revise(
                                    ui->deviceTable->item(row, 8)->text(),
                                    ui->deviceTable->item(row, 0)->text(),
                                    ui->deviceTable->item(row, 5)->text(),
                                    ui->deviceTable->item(row, 3)->text(),
                                    ui->deviceTable->item(row, 4)->text(),
                                    ui->deviceTable->item(row, 1)->text(),
                                    "未连接"
                                    );
                        ipData = "";
                    }
                    /* IPData为空 */
                    else {
                        /* 二次连接 */
                        /* 建立连接 */
                        if(!connectDeviceInfo[i].instructionsService->m_socketClient->isConnected()){
                            connectDeviceInfo[i].instructionsService->establishConnection(preDevIp, preDevPort.toInt());
                        }

                        /* 初始化 */
                        connectDeviceInfo[i].instructionsService->ziJianData.clear();
                        connectDeviceInfo[i].instructionsService->ipData = "";

                        connectDeviceInfo[i].instructionsService->sendIP(ipStringList[0], ipStringList[1], ipStringList[2], ipStringList[3], connectDeviceInfo[i].dev.port);
                        this->sleep(EXPERIMENT_RUNNING_SLEEP_TIME);
                        ipData = connectDeviceInfo[i].instructionsService->getIpData();

                        /* IPData不为空 */
                        if(ipData != 0){
                            cusMsg->show(this, CMsg::CInformation, "设备库", "设备信息修改成功！");

                            /* 更新设备信息 */
                            connectDeviceInfo[i].dev.name = ui->deviceTable->item(row, 0)->text();
                            connectDeviceInfo[i].dev.mac = ui->deviceTable->item(row, 5)->text();
                            connectDeviceInfo[i].dev.ip = ui->deviceTable->item(row, 3)->text();
                            connectDeviceInfo[i].dev.port = ui->deviceTable->item(row, 4)->text();
                            connectDeviceInfo[i].dev.serial_number = ui->deviceTable->item(row, 1)->text();

                            /* 更新数据库设备信息 */
                            DMDB->revise(
                                        ui->deviceTable->item(row, 8)->text(),
                                        ui->deviceTable->item(row, 0)->text(),
                                        ui->deviceTable->item(row, 5)->text(),
                                        ui->deviceTable->item(row, 3)->text(),
                                        ui->deviceTable->item(row, 4)->text(),
                                        ui->deviceTable->item(row, 1)->text(),
                                        "未连接"
                                        );
                            ipData = "";
                        }
                        else {
                            cusMsg->show(this, CMsg::CCritical, "设备库", "设备信息修改失败！\n请检查输入信息、设备连接状态或检查设备是否有故障！");
                            /* 改回原信息 */
                            connectDeviceInfo[i].dev.name = preDevName;
                            connectDeviceInfo[i].dev.ip = preDevIp;
                            connectDeviceInfo[i].dev.port = preDevPort;
                            ipData = "";
                        }
                    }
                    /* ip改变后，设备状态改为未连接，需要手动刷新状态 */
                    connectDeviceInfo[i].dev.status = "未连接";
                    ipData = "";
                    /* 断开连接 */
                    if(connectDeviceInfo[i].instructionsService->m_socketClient->isConnected()){
                        connectDeviceInfo[i].instructionsService->m_socketClient->closeSocket();
                    }
                }
            }
            break;
        }
    }
    ipData = "";
    // 调用show方法
    QList<QHash<QString,QString>> allDeviceInfos = DMDB->show();
    /* 渲染 */
    this->renderDeviceInfo(allDeviceInfos);
}

void SlaveComputerManagement::sleep(int msec){
    QTime dieTime = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < dieTime )
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

void SlaveComputerManagement::closeEvent(QCloseEvent *event){
    qDebug() << "页面关闭";
    emit SlaveComputerManagement::deviceStatusChanged();
}
